'use client';

import { useEffect, useCallback, useState } from 'react';
import { cn } from '@/lib/utils';

interface SmoothScrollOptions {
  duration?: number;
  easing?: 'linear' | 'easeInOut' | 'easeIn' | 'easeOut';
  offset?: number;
  behavior?: 'smooth' | 'instant';
}

/**
 * 平滑滚动工具函数
 */
export class SmoothScroll {
  private static instance: SmoothScroll;
  private isScrolling = false;

  static getInstance(): SmoothScroll {
    if (!SmoothScroll.instance) {
      SmoothScroll.instance = new SmoothScroll();
    }
    return SmoothScroll.instance;
  }

  /**
   * 缓动函数
   */
  private easeInOutQuad(t: number): number {
    return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
  }

  private easeInQuad(t: number): number {
    return t * t;
  }

  private easeOutQuad(t: number): number {
    return t * (2 - t);
  }

  private linear(t: number): number {
    return t;
  }

  private getEasingFunction(easing: string) {
    switch (easing) {
      case 'easeIn':
        return this.easeInQuad;
      case 'easeOut':
        return this.easeOutQuad;
      case 'linear':
        return this.linear;
      default:
        return this.easeInOutQuad;
    }
  }

  /**
   * 滚动到指定位置
   */
  scrollTo(
    target: number | string | Element,
    options: SmoothScrollOptions = {}
  ) {
    const {
      duration = 800,
      easing = 'easeInOut',
      offset = 0,
      behavior = 'smooth',
    } = options;

    // 如果浏览器支持原生平滑滚动且使用默认设置
    if (
      behavior === 'smooth' &&
      'scrollBehavior' in document.documentElement.style
    ) {
      let targetPosition: number;

      if (typeof target === 'number') {
        targetPosition = target;
      } else if (typeof target === 'string') {
        const element = document.querySelector(target);
        if (!element) return;
        targetPosition =
          element.getBoundingClientRect().top + window.pageYOffset;
      } else {
        targetPosition =
          target.getBoundingClientRect().top + window.pageYOffset;
      }

      window.scrollTo({
        top: targetPosition - offset,
        behavior: 'smooth',
      });
      return;
    }

    // 自定义平滑滚动实现
    this.customScrollTo(target, { duration, easing, offset });
  }

  /**
   * 自定义平滑滚动实现
   */
  private customScrollTo(
    target: number | string | Element,
    options: SmoothScrollOptions
  ) {
    if (this.isScrolling) return;

    const { duration = 800, easing = 'easeInOut', offset = 0 } = options;
    const startPosition = window.pageYOffset;
    let targetPosition: number;

    // 确定目标位置
    if (typeof target === 'number') {
      targetPosition = target;
    } else if (typeof target === 'string') {
      const element = document.querySelector(target);
      if (!element) return;
      targetPosition = element.getBoundingClientRect().top + window.pageYOffset;
    } else {
      targetPosition = target.getBoundingClientRect().top + window.pageYOffset;
    }

    targetPosition -= offset;
    const distance = targetPosition - startPosition;
    const easingFunction = this.getEasingFunction(easing);
    let startTime: number | null = null;

    this.isScrolling = true;

    const animation = (currentTime: number) => {
      if (startTime === null) startTime = currentTime;
      const timeElapsed = currentTime - startTime;
      const progress = Math.min(timeElapsed / duration, 1);
      const easedProgress = easingFunction(progress);
      const currentPosition = startPosition + distance * easedProgress;

      window.scrollTo(0, currentPosition);

      if (progress < 1) {
        requestAnimationFrame(animation);
      } else {
        this.isScrolling = false;
      }
    };

    requestAnimationFrame(animation);
  }

  /**
   * 滚动到元素
   */
  scrollToElement(selector: string, options?: SmoothScrollOptions) {
    const element = document.querySelector(selector);
    if (element) {
      this.scrollTo(element, options);
    }
  }

  /**
   * 滚动到顶部
   */
  scrollToTop(options?: SmoothScrollOptions) {
    this.scrollTo(0, options);
  }

  /**
   * 滚动到底部
   */
  scrollToBottom(options?: SmoothScrollOptions) {
    const targetPosition =
      document.documentElement.scrollHeight - window.innerHeight;
    this.scrollTo(targetPosition, options);
  }
}

/**
 * 锚点导航组件
 */
interface AnchorNavProps {
  anchors: Array<{
    id: string;
    label: string;
    href?: string;
  }>;
  className?: string;
  orientation?: 'horizontal' | 'vertical';
  variant?: 'default' | 'pills' | 'underline' | 'dots';
  activeColor?: string;
  offset?: number;
  smooth?: boolean;
}

export function AnchorNav({
  anchors,
  className,
  orientation = 'horizontal',
  variant = 'default',
  activeColor = 'text-blue-600 dark:text-blue-400',
  offset = 80,
  smooth = true,
}: AnchorNavProps) {
  const [activeAnchor, setActiveAnchor] = useState('');
  const smoothScroll = SmoothScroll.getInstance();

  useEffect(() => {
    const observerOptions = {
      root: null,
      rootMargin: `-${offset}px 0px -70% 0px`,
      threshold: 0.1,
    };

    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          setActiveAnchor(entry.target.id);
        }
      });
    }, observerOptions);

    // 观察所有锚点元素
    anchors.forEach(({ id }) => {
      const element = document.getElementById(id);
      if (element) {
        observer.observe(element);
      }
    });

    return () => observer.disconnect();
  }, [anchors, offset]);

  const handleAnchorClick = useCallback(
    (id: string, href?: string) => {
      if (href) {
        window.location.href = href;
        return;
      }

      const element = document.getElementById(id);
      if (element) {
        if (smooth) {
          smoothScroll.scrollToElement(`#${id}`, { offset });
        } else {
          element.scrollIntoView({ behavior: 'instant', block: 'start' });
        }

        // 更新URL hash
        if (window.history.replaceState) {
          window.history.replaceState(null, '', `#${id}`);
        }
      }
    },
    [smooth, offset, smoothScroll]
  );

  const getVariantClasses = () => {
    switch (variant) {
      case 'pills':
        return {
          container:
            orientation === 'horizontal'
              ? 'flex space-x-1'
              : 'flex flex-col space-y-1',
          item: 'px-3 py-2 rounded-full text-sm font-medium transition-all duration-200 hover:bg-gray-100 dark:hover:bg-gray-800',
          active:
            'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400',
        };
      case 'underline':
        return {
          container:
            orientation === 'horizontal'
              ? 'flex space-x-6 border-b border-gray-200 dark:border-gray-700'
              : 'flex flex-col space-y-2 border-l border-gray-200 dark:border-gray-700 pl-4',
          item: 'pb-2 text-sm font-medium transition-all duration-200 hover:text-gray-900 dark:hover:text-gray-100 border-b-2 border-transparent hover:border-gray-300 dark:hover:border-gray-600',
          active: `border-blue-500 ${activeColor}`,
        };
      case 'dots':
        return {
          container:
            orientation === 'horizontal'
              ? 'flex space-x-4'
              : 'flex flex-col space-y-4',
          item: 'flex items-center space-x-2 text-sm font-medium transition-all duration-200 hover:text-gray-900 dark:hover:text-gray-100',
          active: activeColor,
          dot: 'w-2 h-2 rounded-full bg-gray-300 dark:bg-gray-600 transition-all duration-200',
          activeDot: 'bg-blue-500',
        };
      default:
        return {
          container:
            orientation === 'horizontal'
              ? 'flex space-x-4'
              : 'flex flex-col space-y-2',
          item: 'text-sm font-medium transition-all duration-200 hover:text-gray-900 dark:hover:text-gray-100 cursor-pointer',
          active: activeColor,
        };
    }
  };

  const classes = getVariantClasses();

  return (
    <nav className={cn(classes.container, className)}>
      {anchors.map(({ id, label, href }) => {
        const isActive = activeAnchor === id;

        return (
          <button
            key={id}
            onClick={() => handleAnchorClick(id, href)}
            className={cn(classes.item, isActive && classes.active)}
          >
            {variant === 'dots' && (
              <div className={cn(classes.dot, isActive && classes.activeDot)} />
            )}
            {label}
          </button>
        );
      })}
    </nav>
  );
}

/**
 * 目录导航组件
 */
interface TableOfContentsProps {
  headings: Array<{
    id: string;
    text: string;
    level: number;
  }>;
  className?: string;
  maxLevel?: number;
  offset?: number;
}

export function TableOfContents({
  headings,
  className,
  maxLevel = 3,
  offset = 80,
}: TableOfContentsProps) {
  const [activeId, setActiveId] = useState('');
  const smoothScroll = SmoothScroll.getInstance();

  useEffect(() => {
    const observerOptions = {
      root: null,
      rootMargin: `-${offset}px 0px -80% 0px`,
      threshold: 0.1,
    };

    const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          setActiveId(entry.target.id);
        }
      });
    }, observerOptions);

    // 观察所有标题元素
    headings.forEach(({ id }) => {
      const element = document.getElementById(id);
      if (element) {
        observer.observe(element);
      }
    });

    return () => observer.disconnect();
  }, [headings, offset]);

  const handleClick = (id: string) => {
    smoothScroll.scrollToElement(`#${id}`, { offset });

    // 更新URL hash
    if (window.history.replaceState) {
      window.history.replaceState(null, '', `#${id}`);
    }
  };

  const filteredHeadings = headings.filter(h => h.level <= maxLevel);

  if (filteredHeadings.length === 0) return null;

  return (
    <nav className={cn('space-y-1', className)}>
      <h4 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3">
        目录
      </h4>
      <ul className="space-y-1">
        {filteredHeadings.map(({ id, text, level }) => {
          const isActive = activeId === id;
          const indent = (level - 1) * 12;

          return (
            <li key={id}>
              <button
                onClick={() => handleClick(id)}
                className={cn(
                  'block w-full text-left text-sm transition-all duration-200 py-1 px-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800',
                  isActive
                    ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-950 font-medium'
                    : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
                )}
                style={{ paddingLeft: `${8 + indent}px` }}
                title={text}
              >
                <span className="line-clamp-2">{text}</span>
              </button>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

/**
 * 平滑滚动Hook
 */
export function useSmoothScroll(options?: SmoothScrollOptions) {
  const smoothScroll = SmoothScroll.getInstance();

  const scrollTo = useCallback(
    (target: number | string | Element) => {
      smoothScroll.scrollTo(target, options);
    },
    [smoothScroll, options]
  );

  const scrollToElement = useCallback(
    (selector: string) => {
      smoothScroll.scrollToElement(selector, options);
    },
    [smoothScroll, options]
  );

  const scrollToTop = useCallback(() => {
    smoothScroll.scrollToTop(options);
  }, [smoothScroll, options]);

  const scrollToBottom = useCallback(() => {
    smoothScroll.scrollToBottom(options);
  }, [smoothScroll, options]);

  return {
    scrollTo,
    scrollToElement,
    scrollToTop,
    scrollToBottom,
  };
}

/**
 * 自动锚点链接组件
 * 自动为页面中的标题添加锚点链接
 */
export function AutoAnchorLinks({ className }: { className?: string }) {
  useEffect(() => {
    const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');

    headings.forEach(heading => {
      if (!heading.id) {
        // 生成ID
        const id = heading.textContent
          ?.toLowerCase()
          .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
          .replace(/^-+|-+$/g, '');

        if (id) {
          heading.id = id;
        }
      }

      // 添加锚点链接
      if (heading.id && !heading.querySelector('.anchor-link')) {
        const link = document.createElement('a');
        link.href = `#${heading.id}`;
        link.className =
          'anchor-link opacity-0 group-hover:opacity-100 transition-opacity ml-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300';
        link.innerHTML = '#';
        link.setAttribute('aria-label', `链接到 ${heading.textContent}`);

        heading.classList.add('group');
        heading.appendChild(link);

        // 点击事件
        link.addEventListener('click', e => {
          e.preventDefault();
          const smoothScroll = SmoothScroll.getInstance();
          smoothScroll.scrollToElement(`#${heading.id}`, { offset: 80 });

          if (window.history.replaceState) {
            window.history.replaceState(null, '', `#${heading.id}`);
          }
        });
      }
    });
  }, []);

  return null;
}
